package com.minesweeper.ui;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.minesweeper.data.GameData;
import com.minesweeper.data.ImagesData;
import com.minesweeper.tools.BackgroundMusic;
import com.minesweeper.tools.TimerListener;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author skniy
 */
public class GameInterface extends JFrame {

    /**
     * 扫雷面板
     */
    private MinePanel minePanel;
    /**
     * 功能面板
     */
    private FunctionPanel functionPanel;
    /**
     * 游戏菜单栏
     */
    private GameMenuBar gameMenuBar;
    /**
     * 时间类
     */
    private Timer timer;
    /**
     * 线程池
     */
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 构造方法
     */
    public GameInterface() {
        //初始化背景音乐类
        newThreadPoolExecutor();
        BackgroundMusic backgroundMusic = new BackgroundMusic();
        this.threadPoolExecutor.execute(backgroundMusic);
        //初始化时间类
        timer = new Timer(1000, new TimerListener(this));
        //加入菜单栏
        this.gameMenuBar = new GameMenuBar(this);
        this.setJMenuBar(gameMenuBar);
        //加入功能面板
        this.functionPanel = new FunctionPanel(this);
        this.add(this.functionPanel, BorderLayout.NORTH);
        //加入地雷面板
        this.minePanel = new MinePanel(this);
        this.add(this.minePanel, BorderLayout.CENTER);
        //设置一些窗口的自身属性
        //图标
        this.setIconImage(ImagesData.ICON_APPLICATION.getImage());
        //标题
        this.setTitle("扫雷");
        //屏幕中央
        this.setLocationRelativeTo(null);
        //固定大小
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //自适应
        this.pack();
        //可见
        this.setVisible(true);
    }

    /**
     * 新建线程池
     */
    private void newThreadPoolExecutor() {
        //线程池的基本大小
        int corePoolSize = 10;
        //线程池最大数量
        int maximumPoolSizeSize = 100;
        //线程活动保持时间
        long keepAliveTime = 1;
        //任务队列
        ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10);
        this.threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSizeSize, keepAliveTime,
                TimeUnit.SECONDS, workQueue, new ThreadFactoryBuilder().setNameFormat("XX-task-%d").build());
    }

    /**
     * 重新开始游戏
     */
    public void restartGame() {
        //停止计时
        timer.stop();
        //移除面板
        this.remove(functionPanel);
        this.remove(minePanel);
        //重置数据
        GameData.MINE_REMAINING_COUNT = GameData.MINE_COUNT;
        GameData.TIME_COUNT = 0;
        GameData.GAME_STATUS = false;
        newThreadPoolExecutor();
        //添加面板
        functionPanel = new FunctionPanel(this);
        minePanel = new MinePanel(this);
        this.add(functionPanel, BorderLayout.NORTH);
        this.add(minePanel, BorderLayout.CENTER);
        //调整窗口大小并刷新
        this.pack();
        this.validate();
    }

    /**
     * 保存游戏
     *
     * @throws IOException
     */
    public void saveGame() throws IOException {
        //重新建立文件
        File file = new File("data/data.txt");
        file.createNewFile();
        //写入数据
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
        //写入行、列、地雷数目、剩余地雷数目、游戏时间
        outputStreamWriter.write(GameData.ROWS + "\n");
        outputStreamWriter.write(GameData.COLS + "\n");
        outputStreamWriter.write(GameData.MINE_COUNT + "\n");
        outputStreamWriter.write(GameData.MINE_REMAINING_COUNT + "\n");
        outputStreamWriter.write(GameData.TIME_COUNT + "\n");
        outputStreamWriter.write(GameData.GAME_LEVEL + "\n");
        //写入每个格子的flag、周围地雷数目，地雷状态、用户标记的状态和点击状态
        Block[][] blocks = minePanel.getBlocks();
        for (int i = 0; i < GameData.ROWS; i++) {
            for (int j = 0; j < GameData.COLS; j++) {
                outputStreamWriter.write(blocks[i][j].flag + "," + blocks[i][j].localMineCount + "," + blocks[i][j].mineStatus + ","
                        + blocks[i][j].flagStatus + "," + blocks[i][j].clickStatus + "\n");
            }
        }
        outputStreamWriter.close();
    }

    /**
     * 载入游戏
     *
     * @throws IOException
     */
    public void loadGame() throws IOException {
        //查看文件是否存在
        File file = new File("data/data.txt");
        if (file.exists()) {
            //读取文件信息
            InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("data/data.txt"), StandardCharsets.UTF_8);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            //还原游戏数据
            GameData.ROWS = Integer.parseInt(bufferedReader.readLine());
            GameData.COLS = Integer.parseInt(bufferedReader.readLine());
            GameData.MINE_COUNT = Integer.parseInt(bufferedReader.readLine());
            int mineRemainingCount = Integer.parseInt(bufferedReader.readLine());
            int timeCount = Integer.parseInt(bufferedReader.readLine());
            GameData.GAME_LEVEL=Integer.parseInt(bufferedReader.readLine());
            //建立面板
            this.restartGame();
            //继续还原游戏数据
            GameData.MINE_REMAINING_COUNT = mineRemainingCount;
            this.getFunctionPanel().setMineCount(GameData.MINE_REMAINING_COUNT);
            GameData.TIME_COUNT = timeCount;
            GameData.GAME_STATUS = true;
            //设置时间
            this.getFunctionPanel().setTime(GameData.TIME_COUNT);
            //还原每个格子的数据
            Block[][] blocks = this.minePanel.getBlocks();
            for (int i = 0; i < GameData.ROWS; i++) {
                for (int j = 0; j < GameData.COLS; j++) {
                    String[] items = bufferedReader.readLine().split(",");
                    blocks[i][j].flag = Integer.parseInt(items[0]);
                    blocks[i][j].localMineCount = Integer.parseInt(items[1]);
                    blocks[i][j].mineStatus = "true".equals(items[2]);
                    blocks[i][j].flagStatus = "true".equals(items[3]);
                    blocks[i][j].clickStatus = "true".equals(items[4]);
                    //还原每个格子的图标
                    if (blocks[i][j].clickStatus) {
                        blocks[i][j].setIcon(ImagesData.ICON_LOCAL_MINE_NUM[blocks[i][j].localMineCount]);
                    } else if (blocks[i][j].flag == 1) {
                        blocks[i][j].setIcon(ImagesData.ICON_BLOCK_FLAG);
                    } else if (blocks[i][j].flag == 2) {
                        blocks[i][j].setIcon(ImagesData.ICON_BLOCK_UNKNOWN);
                    }
                }
            }
            //启动计时
            this.timer.start();
            bufferedReader.close();
        }

    }

    public FunctionPanel getFunctionPanel() {
        return functionPanel;
    }

    public Timer getTimer() {
        return timer;
    }

    public ThreadPoolExecutor getThreadPoolExecutor() {
        return threadPoolExecutor;
    }

    public MinePanel getMinePanel() {
        return minePanel;
    }
}
